package com.putable.cgw.world.tests;

import java.awt.Dimension;
import java.awt.Point;
import java.util.NoSuchElementException;

import com.putable.cgw.game.member.Member;
import com.putable.cgw.game.member.WeakWall;
import com.putable.cgw.game.yard.ConcreteYard;
import com.putable.cgw.game.yard.Yard;
import com.putable.random.XRandom;

import junit.framework.TestCase;


public class TestYard extends TestCase {
	
	private static final boolean DEBUG = false;
	private static final boolean TO_STRING = true;
	private XRandom rand = new XRandom(1337);

	/**
	 * Makes a <code>Yard</code>
	 * @param dim size of the yard to make.
	 * @return The Yard.
	 */
	private static Yard make(Dimension dim){
		return new ConcreteYard(dim);
	}
	
	/**
	 * Makes a Yard...yay. Also tests that the Dimensions are correct.
	 */
	public void testMake(){
		Yard myYard = make(new Dimension(10000,10));
		assertTrue(myYard.getDimension() != null);
		assertTrue(myYard.getDimension().width == 10000 && 
				myYard.getDimension().height == 10);
	}
	
	public void testPutAndDelete(){
		for(int i = 10; i < 1000; i+=10)putAndDelete(i,i);
		for(int i = 10; i < 1000; i+=10)randomPutAndDelete(i,i);
	}

	private void randomPutAndDelete(int i, int j) {
		Yard yard = make(new Dimension(i,j));
		Member[] puts = new Member[i];
		for(int ind = 0; ind < i; ind++){
			puts[ind] = putRandomMember(yard);
			assertTrue(puts[ind].getYard() != null); 
		}
		for(int ind = 0; ind < i; ind++){
			Point p = puts[ind].getPosition();
			yard.erase(p);
			assertTrue(yard.get(p) == null);
			assertTrue(puts[ind].getYard() == null); 
		}
	}
	
	public void testToString(){
		Yard yar = make(new Dimension(10,10));
		if(TO_STRING)System.out.println(yar.toString());
	}
	
	/**
	 * Generates a random member.
	 * @return the randomly selected member.
	 */
	private Member createRandomMember(){ //TODO Update with diff concrete members.
		int randInt = rand.nextInt(4)+4;
		switch(randInt){
			case 4:
				return new WeakWall();
			case 5:
				return new WeakWall();
			case 6:
				return new WeakWall();
			case 7:
				return new WeakWall();
			default:
				throw new NoSuchElementException("Problem generating random Member.");
		}		
	}
	
	/**
	 * Puts a random Member in the yard in a random place not occupied before.
	 * @param yard The yard to put a random Member in.
	 */
	private Member putRandomMember(Yard yard){
		Member guy = createRandomMember();
		while(true){
			int randX = rand.nextInt(yard.getDimension().width);
			int randY = rand.nextInt(yard.getDimension().height);
			Point randPt = new Point(randX,randY);
			if(yard.get(randPt) == null){
				guy.setPosition(randPt);
				break;
			}
		}
		yard.put(guy);
		return guy;
	}

	private void putAndDelete(int x, int y) {
		Dimension dim = new Dimension(x,y);
		Member[][] ref = new WeakWall[x][y]; //Outside references to the Members we're putting in.
		Yard yard = make (dim);
		double width = dim.getWidth();
		double height = dim.getHeight();
		assertTrue(width == x && height == y);
		int lastSize = 0;
		for(int i = 0; i < 10; i++){
			for(int j = 0; j < 10; j++){
				Point pt = new Point(i,j);
				ref[i][j] = new WeakWall(i,j); //Put the wall where we created it.
				yard.put(ref[i][j]);
				assertTrue(yard.get(pt) != null);
				assertTrue(yard.get(pt) instanceof WeakWall);
				assertTrue(yard.size() > lastSize);
				lastSize = yard.size();
				if(DEBUG)System.out.println(i + "  " + j);
			}
		}
		lastSize = yard.size();
		for(int i = 0; i < 10; i++){
			for(int j = 0; j < 10; j++){
				Point erPt = new Point(i,j);
				yard.erase(erPt);
				assertTrue( yard.get(erPt) == null && yard.size() < lastSize); 
				lastSize = yard.size();
			}
		}
	}
}
